package com.github.kuangcp.graduate.sse.controller;

import com.github.kuangcp.graduate.sse.vo.MsgVO;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author kuangcp
 */
@RestController
@RequestMapping("/async/sse")
public class SseController {

    private static final Map<String, ResponseBodyEmitter> handleMap = new ConcurrentHashMap<>();
    private static final ExecutorService pool = Executors.newFixedThreadPool(3);

    @GetMapping("/events/{id}")
    public ResponseBodyEmitter subscribe(@PathVariable("id") String id, HttpServletResponse response) {
        ResponseBodyEmitter resp = new ResponseBodyEmitter();
        handleMap.put(id, resp);
        resp.onCompletion(() -> handleMap.remove(id));
        resp.onError(v -> handleMap.remove(id));
        resp.onTimeout(() -> handleMap.remove(id));

        pool.execute(() -> {
            try {
                resp.send(new MsgVO(System.nanoTime() + "", 2000L).buildMsg());
                for (int i = 0; i < 7; i++) {
                    Thread.sleep(500);
//                    System.out.println(i);
                    Date date = new Date();
                    resp.send(new MsgVO(System.nanoTime() + "", date.getSeconds() + "s,").buildMsg());
                }
                resp.send(new MsgVO(System.nanoTime() + "", " end ").buildMsg());
                for (int i = 0; i < 5; i++) {
                    Thread.sleep(200);
                    resp.send(MsgVO.COMMENT);
                }
                resp.complete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        response.setContentType("text/event-stream");
        return resp;
    }

    @GetMapping("/send/{id}")
    public String send(@PathVariable("id") String id, String msg) {
        ResponseBodyEmitter responseBodyEmitter = handleMap.get(id);
        if (Objects.isNull(responseBodyEmitter)) {
            return "not exist";
        }
        try {
            responseBodyEmitter.send("data: " + msg + "\n\n", MediaType.TEXT_EVENT_STREAM);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "send OK";
    }

    @GetMapping("/complete/{id}")
    public String complete(@PathVariable("id") String id) {
        ResponseBodyEmitter responseBodyEmitter = handleMap.get(id);
        if (Objects.isNull(responseBodyEmitter)) {
            return "not exist";
        }
        responseBodyEmitter.complete();
        handleMap.remove(id);
        return "complete OK";
    }
}
